use common_enums::{PaymentMethodType, RequestIncrementalAuthorization};
use common_types::primitive_wrappers::{
    EnablePartialAuthorizationBool, RequestExtendedAuthorizationBool,
};
use common_utils::{encryption::Encryption, pii, types::MinorUnit};
use diesel::{AsChangeset, Identifiable, Insertable, Queryable, Selectable};
use masking::ExposeInterface;
use serde::{Deserialize, Serialize};
use time::PrimitiveDateTime;

#[cfg(feature = "v1")]
use crate::schema::payment_intent;
#[cfg(feature = "v2")]
use crate::schema_v2::payment_intent;
#[cfg(feature = "v2")]
use crate::types::{FeatureMetadata, OrderDetailsWithAmount};
#[cfg(feature = "v2")]
use crate::RequiredFromNullable;
use crate::{business_profile::PaymentLinkBackgroundImageConfig, enums as storage_enums};

#[cfg(feature = "v2")]
#[derive(Clone, Debug, PartialEq, Identifiable, Queryable, Serialize, Deserialize, Selectable)]
#[diesel(table_name = payment_intent, primary_key(id), check_for_backend(diesel::pg::Pg))]
pub struct PaymentIntent {
    pub merchant_id: common_utils::id_type::MerchantId,
    pub status: storage_enums::IntentStatus,
    pub amount: MinorUnit,
    #[diesel(deserialize_as = RequiredFromNullable<storage_enums::Currency>)]
    pub currency: storage_enums::Currency,
    pub amount_captured: Option<MinorUnit>,
    pub customer_id: Option<common_utils::id_type::GlobalCustomerId>,
    pub description: Option<common_utils::types::Description>,
    pub return_url: Option<common_utils::types::Url>,
    pub metadata: Option<pii::SecretSerdeValue>,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub created_at: PrimitiveDateTime,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub modified_at: PrimitiveDateTime,
    #[serde(default, with = "common_utils::custom_serde::iso8601::option")]
    pub last_synced: Option<PrimitiveDateTime>,
    pub setup_future_usage: Option<storage_enums::FutureUsage>,
    pub active_attempt_id: Option<common_utils::id_type::GlobalAttemptId>,
    #[diesel(deserialize_as = super::OptionalDieselArray<masking::Secret<OrderDetailsWithAmount>>)]
    pub order_details: Option<Vec<masking::Secret<OrderDetailsWithAmount>>>,
    pub allowed_payment_method_types: Option<pii::SecretSerdeValue>,
    pub connector_metadata: Option<pii::SecretSerdeValue>,
    pub feature_metadata: Option<FeatureMetadata>,
    pub attempt_count: i16,
    #[diesel(deserialize_as = RequiredFromNullable<common_utils::id_type::ProfileId>)]
    pub profile_id: common_utils::id_type::ProfileId,
    pub payment_link_id: Option<String>,
    pub updated_by: String,
    pub surcharge_applicable: Option<bool>,
    pub request_incremental_authorization: Option<RequestIncrementalAuthorization>,
    pub authorization_count: Option<i32>,
    #[diesel(deserialize_as = RequiredFromNullable<PrimitiveDateTime>)]
    pub session_expiry: PrimitiveDateTime,
    pub request_external_three_ds_authentication: Option<bool>,
    pub frm_metadata: Option<pii::SecretSerdeValue>,
    pub customer_details: Option<Encryption>,
    pub shipping_cost: Option<MinorUnit>,
    pub organization_id: common_utils::id_type::OrganizationId,
    pub tax_details: Option<TaxDetails>,
    pub skip_external_tax_calculation: Option<bool>,
    pub request_extended_authorization: Option<RequestExtendedAuthorizationBool>,
    pub psd2_sca_exemption_type: Option<storage_enums::ScaExemptionType>,
    pub split_payments: Option<common_types::payments::SplitPaymentsRequest>,
    pub platform_merchant_id: Option<common_utils::id_type::MerchantId>,
    pub force_3ds_challenge: Option<bool>,
    pub force_3ds_challenge_trigger: Option<bool>,
    pub processor_merchant_id: Option<common_utils::id_type::MerchantId>,
    pub created_by: Option<String>,
    pub is_iframe_redirection_enabled: Option<bool>,
    pub is_payment_id_from_merchant: Option<bool>,
    pub payment_channel: Option<common_enums::PaymentChannel>,
    pub tax_status: Option<common_enums::TaxStatus>,
    pub discount_amount: Option<MinorUnit>,
    pub shipping_amount_tax: Option<MinorUnit>,
    pub duty_amount: Option<MinorUnit>,
    pub order_date: Option<PrimitiveDateTime>,
    pub enable_partial_authorization: Option<EnablePartialAuthorizationBool>,
    pub enable_overcapture: Option<common_types::primitive_wrappers::EnableOvercaptureBool>,
    pub mit_category: Option<storage_enums::MitCategory>,
    pub billing_descriptor: Option<common_types::payments::BillingDescriptor>,
    pub tokenization: Option<common_enums::Tokenization>,
    pub partner_merchant_identifier_details:
        Option<common_types::payments::PartnerMerchantIdentifierDetails>,
    pub merchant_reference_id: Option<common_utils::id_type::PaymentReferenceId>,
    pub billing_address: Option<Encryption>,
    pub shipping_address: Option<Encryption>,
    pub capture_method: Option<storage_enums::CaptureMethod>,
    pub authentication_type: Option<common_enums::AuthenticationType>,
    pub prerouting_algorithm: Option<serde_json::Value>,
    pub surcharge_amount: Option<MinorUnit>,
    pub tax_on_surcharge: Option<MinorUnit>,
    // Denotes the action(approve or reject) taken by merchant in case of manual review.
    // Manual review can occur when the transaction is marked as risky by the frm_processor, payment processor or when there is underpayment/over payment incase of crypto payment
    pub frm_merchant_decision: Option<common_enums::MerchantDecision>,
    pub statement_descriptor: Option<common_utils::types::StatementDescriptor>,
    pub enable_payment_link: Option<bool>,
    pub apply_mit_exemption: Option<bool>,
    pub customer_present: Option<bool>,
    pub routing_algorithm_id: Option<common_utils::id_type::RoutingId>,
    pub payment_link_config: Option<PaymentLinkConfigRequestForPayments>,
    pub id: common_utils::id_type::GlobalPaymentId,
    pub split_txns_enabled: Option<common_enums::SplitTxnsEnabled>,
    pub active_attempts_group_id: Option<common_utils::id_type::GlobalAttemptGroupId>,
    pub active_attempt_id_type: Option<common_enums::ActiveAttemptIDType>,
}

#[cfg(feature = "v1")]
#[derive(Clone, Debug, PartialEq, Identifiable, Queryable, Serialize, Deserialize, Selectable)]
#[diesel(table_name = payment_intent, primary_key(payment_id, merchant_id), check_for_backend(diesel::pg::Pg))]
pub struct PaymentIntent {
    pub payment_id: common_utils::id_type::PaymentId,
    pub merchant_id: common_utils::id_type::MerchantId,
    pub status: storage_enums::IntentStatus,
    pub amount: MinorUnit,
    pub currency: Option<storage_enums::Currency>,
    pub amount_captured: Option<MinorUnit>,
    pub customer_id: Option<common_utils::id_type::CustomerId>,
    pub description: Option<String>,
    pub return_url: Option<String>,
    pub metadata: Option<serde_json::Value>,
    pub connector_id: Option<String>,
    pub shipping_address_id: Option<String>,
    pub billing_address_id: Option<String>,
    pub statement_descriptor_name: Option<String>,
    pub statement_descriptor_suffix: Option<String>,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub created_at: PrimitiveDateTime,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub modified_at: PrimitiveDateTime,
    #[serde(default, with = "common_utils::custom_serde::iso8601::option")]
    pub last_synced: Option<PrimitiveDateTime>,
    pub setup_future_usage: Option<storage_enums::FutureUsage>,
    pub off_session: Option<bool>,
    pub client_secret: Option<String>,
    pub active_attempt_id: String,
    pub business_country: Option<storage_enums::CountryAlpha2>,
    pub business_label: Option<String>,
    #[diesel(deserialize_as = super::OptionalDieselArray<pii::SecretSerdeValue>)]
    pub order_details: Option<Vec<pii::SecretSerdeValue>>,
    pub allowed_payment_method_types: Option<serde_json::Value>,
    pub connector_metadata: Option<serde_json::Value>,
    pub feature_metadata: Option<serde_json::Value>,
    pub attempt_count: i16,
    pub profile_id: Option<common_utils::id_type::ProfileId>,
    // Denotes the action(approve or reject) taken by merchant in case of manual review.
    // Manual review can occur when the transaction is marked as risky by the frm_processor, payment processor or when there is underpayment/over payment incase of crypto payment
    pub merchant_decision: Option<String>,
    pub payment_link_id: Option<String>,
    pub payment_confirm_source: Option<storage_enums::PaymentSource>,
    pub updated_by: String,
    pub surcharge_applicable: Option<bool>,
    pub request_incremental_authorization: Option<RequestIncrementalAuthorization>,
    pub incremental_authorization_allowed: Option<bool>,
    pub authorization_count: Option<i32>,
    pub session_expiry: Option<PrimitiveDateTime>,
    pub fingerprint_id: Option<String>,
    pub request_external_three_ds_authentication: Option<bool>,
    pub charges: Option<pii::SecretSerdeValue>,
    pub frm_metadata: Option<pii::SecretSerdeValue>,
    pub customer_details: Option<Encryption>,
    pub billing_details: Option<Encryption>,
    pub merchant_order_reference_id: Option<String>,
    pub shipping_details: Option<Encryption>,
    pub is_payment_processor_token_flow: Option<bool>,
    pub shipping_cost: Option<MinorUnit>,
    pub organization_id: common_utils::id_type::OrganizationId,
    pub tax_details: Option<TaxDetails>,
    pub skip_external_tax_calculation: Option<bool>,
    pub request_extended_authorization: Option<RequestExtendedAuthorizationBool>,
    pub psd2_sca_exemption_type: Option<storage_enums::ScaExemptionType>,
    pub split_payments: Option<common_types::payments::SplitPaymentsRequest>,
    pub platform_merchant_id: Option<common_utils::id_type::MerchantId>,
    pub force_3ds_challenge: Option<bool>,
    pub force_3ds_challenge_trigger: Option<bool>,
    pub processor_merchant_id: Option<common_utils::id_type::MerchantId>,
    pub created_by: Option<String>,
    pub is_iframe_redirection_enabled: Option<bool>,
    pub extended_return_url: Option<String>,
    pub is_payment_id_from_merchant: Option<bool>,
    pub payment_channel: Option<common_enums::PaymentChannel>,
    pub tax_status: Option<common_enums::TaxStatus>,
    pub discount_amount: Option<MinorUnit>,
    pub shipping_amount_tax: Option<MinorUnit>,
    pub duty_amount: Option<MinorUnit>,
    pub order_date: Option<PrimitiveDateTime>,
    pub enable_partial_authorization: Option<EnablePartialAuthorizationBool>,
    pub enable_overcapture: Option<common_types::primitive_wrappers::EnableOvercaptureBool>,
    pub mit_category: Option<storage_enums::MitCategory>,
    pub billing_descriptor: Option<common_types::payments::BillingDescriptor>,
    pub tokenization: Option<common_enums::Tokenization>,
    pub partner_merchant_identifier_details:
        Option<common_types::payments::PartnerMerchantIdentifierDetails>,
}

#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, diesel::AsExpression, PartialEq)]
#[diesel(sql_type = diesel::sql_types::Jsonb)]
pub struct PaymentLinkConfigRequestForPayments {
    /// custom theme for the payment link
    pub theme: Option<String>,
    /// merchant display logo
    pub logo: Option<String>,
    /// Custom merchant name for payment link
    pub seller_name: Option<String>,
    /// Custom layout for sdk
    pub sdk_layout: Option<String>,
    /// Display only the sdk for payment link
    pub display_sdk_only: Option<bool>,
    /// Enable saved payment method option for payment link
    pub enabled_saved_payment_method: Option<bool>,
    /// Hide card nickname field option for payment link
    pub hide_card_nickname_field: Option<bool>,
    /// Show card form by default for payment link
    pub show_card_form_by_default: Option<bool>,
    /// Dynamic details related to merchant to be rendered in payment link
    pub transaction_details: Option<Vec<PaymentLinkTransactionDetails>>,
    /// Configurations for the background image for details section
    pub background_image: Option<PaymentLinkBackgroundImageConfig>,
    /// Custom layout for details section
    pub details_layout: Option<common_enums::PaymentLinkDetailsLayout>,
    /// Text for payment link's handle confirm button
    pub payment_button_text: Option<String>,
    /// Skip the status screen after payment completion
    pub skip_status_screen: Option<bool>,
    /// Text for customizing message for card terms
    pub custom_message_for_card_terms: Option<String>,
    /// Text for customizing message for different Payment Method Types
    pub custom_message_for_payment_method_types:
        Option<common_enums::CustomTermsByPaymentMethodTypes>,
    /// Custom background colour for payment link's handle confirm button
    pub payment_button_colour: Option<String>,
    /// Custom text colour for payment link's handle confirm button
    pub payment_button_text_colour: Option<String>,
    /// Custom background colour for the payment link
    pub background_colour: Option<String>,
    /// SDK configuration rules
    pub sdk_ui_rules:
        Option<std::collections::HashMap<String, std::collections::HashMap<String, String>>>,
    /// Payment link configuration rules
    pub payment_link_ui_rules:
        Option<std::collections::HashMap<String, std::collections::HashMap<String, String>>>,
    /// Flag to enable the button only when the payment form is ready for submission
    pub enable_button_only_on_form_ready: Option<bool>,
    /// Optional header for the SDK's payment form
    pub payment_form_header_text: Option<String>,
    /// Label type in the SDK's payment form
    pub payment_form_label_type: Option<common_enums::PaymentLinkSdkLabelType>,
    /// Boolean for controlling whether or not to show the explicit consent for storing cards
    pub show_card_terms: Option<common_enums::PaymentLinkShowSdkTerms>,
    /// Boolean to control payment button text for setup mandate calls
    pub is_setup_mandate_flow: Option<bool>,
    /// Hex color for the CVC icon during error state
    pub color_icon_card_cvc_error: Option<String>,
}

common_utils::impl_to_sql_from_sql_json!(PaymentLinkConfigRequestForPayments);

#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, PartialEq)]
pub struct PaymentLinkTransactionDetails {
    /// Key for the transaction details
    pub key: String,
    /// Value for the transaction details
    pub value: String,
    /// UI configuration for the transaction details
    pub ui_configuration: Option<TransactionDetailsUiConfiguration>,
}

common_utils::impl_to_sql_from_sql_json!(PaymentLinkTransactionDetails);

#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, PartialEq)]
pub struct TransactionDetailsUiConfiguration {
    /// Position of the key-value pair in the UI
    pub position: Option<i8>,
    /// Whether the key should be bold
    pub is_key_bold: Option<bool>,
    /// Whether the value should be bold
    pub is_value_bold: Option<bool>,
}

common_utils::impl_to_sql_from_sql_json!(TransactionDetailsUiConfiguration);

#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, diesel::AsExpression)]
#[diesel(sql_type = diesel::sql_types::Jsonb)]
pub struct TaxDetails {
    /// This is the tax related information that is calculated irrespective of any payment method.
    /// This is calculated when the order is created with shipping details
    pub default: Option<DefaultTax>,

    /// This is the tax related information that is calculated based on the payment method
    /// This is calculated when calling the /calculate_tax API
    pub payment_method_type: Option<PaymentMethodTypeTax>,
}

impl TaxDetails {
    /// Get the tax amount
    /// If default tax is present, return the default tax amount
    /// If default tax is not present, return the tax amount based on the payment method if it matches the provided payment method type
    pub fn get_tax_amount(&self, payment_method: Option<PaymentMethodType>) -> Option<MinorUnit> {
        self.payment_method_type
            .as_ref()
            .zip(payment_method)
            .filter(|(payment_method_type_tax, payment_method)| {
                payment_method_type_tax.pmt == *payment_method
            })
            .map(|(payment_method_type_tax, _)| payment_method_type_tax.order_tax_amount)
            .or_else(|| self.get_default_tax_amount())
    }

    /// Get the default tax amount
    pub fn get_default_tax_amount(&self) -> Option<MinorUnit> {
        self.default
            .as_ref()
            .map(|default_tax_details| default_tax_details.order_tax_amount)
    }
}

common_utils::impl_to_sql_from_sql_json!(TaxDetails);

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct PaymentMethodTypeTax {
    pub order_tax_amount: MinorUnit,
    pub pmt: PaymentMethodType,
}

#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
pub struct DefaultTax {
    pub order_tax_amount: MinorUnit,
}

#[cfg(feature = "v2")]
#[derive(
    Clone, Debug, PartialEq, Insertable, router_derive::DebugAsDisplay, Serialize, Deserialize,
)]
#[diesel(table_name = payment_intent)]
pub struct PaymentIntentNew {
    pub merchant_id: common_utils::id_type::MerchantId,
    pub status: storage_enums::IntentStatus,
    pub amount: MinorUnit,
    pub currency: storage_enums::Currency,
    pub amount_captured: Option<MinorUnit>,
    pub customer_id: Option<common_utils::id_type::GlobalCustomerId>,
    pub description: Option<common_utils::types::Description>,
    pub return_url: Option<common_utils::types::Url>,
    pub metadata: Option<pii::SecretSerdeValue>,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub created_at: PrimitiveDateTime,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub modified_at: PrimitiveDateTime,
    #[serde(default, with = "common_utils::custom_serde::iso8601::option")]
    pub last_synced: Option<PrimitiveDateTime>,
    pub setup_future_usage: Option<storage_enums::FutureUsage>,
    pub active_attempt_id: Option<common_utils::id_type::GlobalAttemptId>,
    #[diesel(deserialize_as = super::OptionalDieselArray<masking::Secret<OrderDetailsWithAmount>>)]
    pub order_details: Option<Vec<masking::Secret<OrderDetailsWithAmount>>>,
    pub allowed_payment_method_types: Option<pii::SecretSerdeValue>,
    pub connector_metadata: Option<pii::SecretSerdeValue>,
    pub feature_metadata: Option<FeatureMetadata>,
    pub attempt_count: i16,
    pub profile_id: common_utils::id_type::ProfileId,
    pub payment_link_id: Option<String>,
    pub updated_by: String,
    pub surcharge_applicable: Option<bool>,
    pub request_incremental_authorization: Option<RequestIncrementalAuthorization>,
    pub authorization_count: Option<i32>,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub session_expiry: PrimitiveDateTime,
    pub request_external_three_ds_authentication: Option<bool>,
    pub frm_metadata: Option<pii::SecretSerdeValue>,
    pub customer_details: Option<Encryption>,
    pub shipping_cost: Option<MinorUnit>,
    pub organization_id: common_utils::id_type::OrganizationId,
    pub tax_details: Option<TaxDetails>,
    pub skip_external_tax_calculation: Option<bool>,
    pub enable_partial_authorization: Option<EnablePartialAuthorizationBool>,
    pub split_txns_enabled: Option<common_enums::SplitTxnsEnabled>,
    pub merchant_reference_id: Option<common_utils::id_type::PaymentReferenceId>,
    pub billing_address: Option<Encryption>,
    pub shipping_address: Option<Encryption>,
    pub capture_method: Option<storage_enums::CaptureMethod>,
    pub authentication_type: Option<common_enums::AuthenticationType>,
    pub prerouting_algorithm: Option<serde_json::Value>,
    pub surcharge_amount: Option<MinorUnit>,
    pub tax_on_surcharge: Option<MinorUnit>,
    pub frm_merchant_decision: Option<common_enums::MerchantDecision>,
    pub statement_descriptor: Option<common_utils::types::StatementDescriptor>,
    pub enable_payment_link: Option<bool>,
    pub apply_mit_exemption: Option<bool>,
    pub id: common_utils::id_type::GlobalPaymentId,
    pub platform_merchant_id: Option<common_utils::id_type::MerchantId>,
    pub force_3ds_challenge: Option<bool>,
    pub force_3ds_challenge_trigger: Option<bool>,
    pub processor_merchant_id: Option<common_utils::id_type::MerchantId>,
    pub routing_algorithm_id: Option<common_utils::id_type::RoutingId>,
    pub created_by: Option<String>,
    pub is_iframe_redirection_enabled: Option<bool>,
    pub is_payment_id_from_merchant: Option<bool>,
    pub payment_channel: Option<common_enums::PaymentChannel>,
    pub tax_status: Option<common_enums::TaxStatus>,
    pub discount_amount: Option<MinorUnit>,
    pub shipping_amount_tax: Option<MinorUnit>,
    pub duty_amount: Option<MinorUnit>,
    pub order_date: Option<PrimitiveDateTime>,
    pub mit_category: Option<storage_enums::MitCategory>,
    pub tokenization: Option<common_enums::Tokenization>,
    pub active_attempts_group_id: Option<common_utils::id_type::GlobalAttemptGroupId>,
    pub active_attempt_id_type: Option<common_enums::ActiveAttemptIDType>,
}

#[cfg(feature = "v1")]
#[derive(
    Clone, Debug, PartialEq, Insertable, router_derive::DebugAsDisplay, Serialize, Deserialize,
)]
#[diesel(table_name = payment_intent)]
pub struct PaymentIntentNew {
    pub payment_id: common_utils::id_type::PaymentId,
    pub merchant_id: common_utils::id_type::MerchantId,
    pub status: storage_enums::IntentStatus,
    pub amount: MinorUnit,
    pub currency: Option<storage_enums::Currency>,
    pub amount_captured: Option<MinorUnit>,
    pub customer_id: Option<common_utils::id_type::CustomerId>,
    pub description: Option<String>,
    pub return_url: Option<String>,
    pub metadata: Option<serde_json::Value>,
    pub connector_id: Option<String>,
    pub shipping_address_id: Option<String>,
    pub billing_address_id: Option<String>,
    pub statement_descriptor_name: Option<String>,
    pub statement_descriptor_suffix: Option<String>,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub created_at: PrimitiveDateTime,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub modified_at: PrimitiveDateTime,
    #[serde(default, with = "common_utils::custom_serde::iso8601::option")]
    pub last_synced: Option<PrimitiveDateTime>,
    pub setup_future_usage: Option<storage_enums::FutureUsage>,
    pub off_session: Option<bool>,
    pub client_secret: Option<String>,
    pub active_attempt_id: String,
    pub business_country: Option<storage_enums::CountryAlpha2>,
    pub business_label: Option<String>,
    #[diesel(deserialize_as = super::OptionalDieselArray<pii::SecretSerdeValue>)]
    pub order_details: Option<Vec<pii::SecretSerdeValue>>,
    pub allowed_payment_method_types: Option<serde_json::Value>,
    pub connector_metadata: Option<serde_json::Value>,
    pub feature_metadata: Option<serde_json::Value>,
    pub attempt_count: i16,
    pub profile_id: Option<common_utils::id_type::ProfileId>,
    pub merchant_decision: Option<String>,
    pub payment_link_id: Option<String>,
    pub payment_confirm_source: Option<storage_enums::PaymentSource>,
    pub updated_by: String,
    pub surcharge_applicable: Option<bool>,
    pub request_incremental_authorization: Option<RequestIncrementalAuthorization>,
    pub incremental_authorization_allowed: Option<bool>,
    pub authorization_count: Option<i32>,
    #[serde(default, with = "common_utils::custom_serde::iso8601::option")]
    pub session_expiry: Option<PrimitiveDateTime>,
    pub fingerprint_id: Option<String>,
    pub request_external_three_ds_authentication: Option<bool>,
    pub charges: Option<pii::SecretSerdeValue>,
    pub frm_metadata: Option<pii::SecretSerdeValue>,
    pub customer_details: Option<Encryption>,
    pub billing_details: Option<Encryption>,
    pub merchant_order_reference_id: Option<String>,
    pub shipping_details: Option<Encryption>,
    pub is_payment_processor_token_flow: Option<bool>,
    pub shipping_cost: Option<MinorUnit>,
    pub organization_id: common_utils::id_type::OrganizationId,
    pub tax_details: Option<TaxDetails>,
    pub skip_external_tax_calculation: Option<bool>,
    pub request_extended_authorization: Option<RequestExtendedAuthorizationBool>,
    pub psd2_sca_exemption_type: Option<storage_enums::ScaExemptionType>,
    pub split_payments: Option<common_types::payments::SplitPaymentsRequest>,
    pub platform_merchant_id: Option<common_utils::id_type::MerchantId>,
    pub force_3ds_challenge: Option<bool>,
    pub force_3ds_challenge_trigger: Option<bool>,
    pub processor_merchant_id: Option<common_utils::id_type::MerchantId>,
    pub created_by: Option<String>,
    pub is_iframe_redirection_enabled: Option<bool>,
    pub extended_return_url: Option<String>,
    pub is_payment_id_from_merchant: Option<bool>,
    pub payment_channel: Option<common_enums::PaymentChannel>,
    pub tax_status: Option<common_enums::TaxStatus>,
    pub discount_amount: Option<MinorUnit>,
    pub order_date: Option<PrimitiveDateTime>,
    pub shipping_amount_tax: Option<MinorUnit>,
    pub duty_amount: Option<MinorUnit>,
    pub enable_partial_authorization: Option<EnablePartialAuthorizationBool>,
    pub enable_overcapture: Option<common_types::primitive_wrappers::EnableOvercaptureBool>,
    pub mit_category: Option<storage_enums::MitCategory>,
    pub billing_descriptor: Option<common_types::payments::BillingDescriptor>,
    pub tokenization: Option<common_enums::Tokenization>,
    pub partner_merchant_identifier_details:
        Option<common_types::payments::PartnerMerchantIdentifierDetails>,
}

#[cfg(feature = "v2")]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum PaymentIntentUpdate {
    /// Update the payment intent details on payment intent confirmation, before calling the connector
    ConfirmIntent {
        status: storage_enums::IntentStatus,
        active_attempt_id: common_utils::id_type::GlobalAttemptId,
        updated_by: String,
    },
    /// Update the payment intent details on payment intent confirmation, after calling the connector
    ConfirmIntentPostUpdate {
        status: storage_enums::IntentStatus,
        amount_captured: Option<MinorUnit>,
        updated_by: String,
    },
}

#[cfg(feature = "v1")]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum PaymentIntentUpdate {
    ResponseUpdate {
        status: storage_enums::IntentStatus,
        amount_captured: Option<MinorUnit>,
        fingerprint_id: Option<String>,
        updated_by: String,
        incremental_authorization_allowed: Option<bool>,
        feature_metadata: Option<masking::Secret<serde_json::Value>>,
    },
    MetadataUpdate {
        metadata: serde_json::Value,
        updated_by: String,
    },
    Update(Box<PaymentIntentUpdateFields>),
    PaymentCreateUpdate {
        return_url: Option<String>,
        status: Option<storage_enums::IntentStatus>,
        customer_id: Option<common_utils::id_type::CustomerId>,
        shipping_address_id: Option<String>,
        billing_address_id: Option<String>,
        customer_details: Option<Encryption>,
        updated_by: String,
    },
    MerchantStatusUpdate {
        status: storage_enums::IntentStatus,
        shipping_address_id: Option<String>,
        billing_address_id: Option<String>,
        updated_by: String,
    },
    PGStatusUpdate {
        status: storage_enums::IntentStatus,
        updated_by: String,
        incremental_authorization_allowed: Option<bool>,
        feature_metadata: Option<masking::Secret<serde_json::Value>>,
    },
    PaymentAttemptAndAttemptCountUpdate {
        active_attempt_id: String,
        attempt_count: i16,
        updated_by: String,
    },
    StatusAndAttemptUpdate {
        status: storage_enums::IntentStatus,
        active_attempt_id: String,
        attempt_count: i16,
        updated_by: String,
    },
    ApproveUpdate {
        status: storage_enums::IntentStatus,
        merchant_decision: Option<String>,
        updated_by: String,
    },
    RejectUpdate {
        status: storage_enums::IntentStatus,
        merchant_decision: Option<String>,
        updated_by: String,
    },
    SurchargeApplicableUpdate {
        surcharge_applicable: Option<bool>,
        updated_by: String,
    },
    IncrementalAuthorizationAmountUpdate {
        amount: MinorUnit,
    },
    AuthorizationCountUpdate {
        authorization_count: i32,
    },
    CompleteAuthorizeUpdate {
        shipping_address_id: Option<String>,
    },
    ManualUpdate {
        status: Option<storage_enums::IntentStatus>,
        updated_by: String,
    },
    SessionResponseUpdate {
        tax_details: TaxDetails,
        shipping_address_id: Option<String>,
        updated_by: String,
        shipping_details: Option<Encryption>,
    },
}

#[cfg(feature = "v2")]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PaymentIntentUpdateFields {
    pub amount: MinorUnit,
    pub currency: storage_enums::Currency,
    pub setup_future_usage: Option<storage_enums::FutureUsage>,
    pub status: storage_enums::IntentStatus,
    pub customer_id: Option<common_utils::id_type::CustomerId>,
    pub shipping_address: Option<Encryption>,
    pub billing_address: Option<Encryption>,
    pub return_url: Option<String>,
    pub description: Option<String>,
    pub statement_descriptor: Option<String>,
    pub order_details: Option<Vec<pii::SecretSerdeValue>>,
    pub metadata: Option<pii::SecretSerdeValue>,
    pub payment_confirm_source: Option<storage_enums::PaymentSource>,
    pub updated_by: String,
    pub session_expiry: Option<PrimitiveDateTime>,
    pub request_external_three_ds_authentication: Option<bool>,
    pub frm_metadata: Option<pii::SecretSerdeValue>,
    pub customer_details: Option<Encryption>,
    pub merchant_order_reference_id: Option<String>,
    pub is_payment_processor_token_flow: Option<bool>,
    pub force_3ds_challenge: Option<bool>,
    pub is_iframe_redirection_enabled: Option<bool>,
    pub payment_channel: Option<Option<common_enums::PaymentChannel>>,
}

#[cfg(feature = "v1")]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PaymentIntentUpdateFields {
    pub amount: MinorUnit,
    pub currency: storage_enums::Currency,
    pub setup_future_usage: Option<storage_enums::FutureUsage>,
    pub status: storage_enums::IntentStatus,
    pub customer_id: Option<common_utils::id_type::CustomerId>,
    pub shipping_address_id: Option<String>,
    pub billing_address_id: Option<String>,
    pub return_url: Option<String>,
    pub business_country: Option<storage_enums::CountryAlpha2>,
    pub business_label: Option<String>,
    pub description: Option<String>,
    pub statement_descriptor_name: Option<String>,
    pub statement_descriptor_suffix: Option<String>,
    pub order_details: Option<Vec<pii::SecretSerdeValue>>,
    pub metadata: Option<serde_json::Value>,
    pub payment_confirm_source: Option<storage_enums::PaymentSource>,
    pub updated_by: String,
    pub session_expiry: Option<PrimitiveDateTime>,
    pub fingerprint_id: Option<String>,
    pub request_external_three_ds_authentication: Option<bool>,
    pub frm_metadata: Option<pii::SecretSerdeValue>,
    pub customer_details: Option<Encryption>,
    pub billing_details: Option<Encryption>,
    pub merchant_order_reference_id: Option<String>,
    pub shipping_details: Option<Encryption>,
    pub is_payment_processor_token_flow: Option<bool>,
    pub tax_details: Option<TaxDetails>,
    pub force_3ds_challenge: Option<bool>,
    pub is_iframe_redirection_enabled: Option<bool>,
    pub payment_channel: Option<common_enums::PaymentChannel>,
    pub feature_metadata: Option<masking::Secret<serde_json::Value>>,
    pub tax_status: Option<common_enums::TaxStatus>,
    pub discount_amount: Option<MinorUnit>,
    pub order_date: Option<PrimitiveDateTime>,
    pub shipping_amount_tax: Option<MinorUnit>,
    pub duty_amount: Option<MinorUnit>,
    pub enable_partial_authorization: Option<EnablePartialAuthorizationBool>,
    pub enable_overcapture: Option<common_types::primitive_wrappers::EnableOvercaptureBool>,
}

// TODO: uncomment fields as necessary
#[cfg(feature = "v2")]
#[derive(Clone, Debug, AsChangeset, router_derive::DebugAsDisplay, Serialize, Deserialize)]
#[diesel(table_name = payment_intent)]
pub struct PaymentIntentUpdateInternal {
    pub status: Option<storage_enums::IntentStatus>,
    pub prerouting_algorithm: Option<serde_json::Value>,
    pub amount_captured: Option<MinorUnit>,
    pub modified_at: PrimitiveDateTime,
    pub active_attempt_id: Option<Option<common_utils::id_type::GlobalAttemptId>>,
    pub active_attempts_group_id: Option<common_utils::id_type::GlobalAttemptGroupId>,
    pub active_attempt_id_type: Option<common_enums::ActiveAttemptIDType>,
    pub amount: Option<MinorUnit>,
    pub currency: Option<storage_enums::Currency>,
    pub shipping_cost: Option<MinorUnit>,
    pub tax_details: Option<TaxDetails>,
    pub skip_external_tax_calculation: Option<bool>,
    pub surcharge_applicable: Option<bool>,
    pub surcharge_amount: Option<MinorUnit>,
    pub tax_on_surcharge: Option<MinorUnit>,
    pub routing_algorithm_id: Option<common_utils::id_type::RoutingId>,
    pub capture_method: Option<common_enums::CaptureMethod>,
    pub authentication_type: Option<common_enums::AuthenticationType>,
    pub billing_address: Option<Encryption>,
    pub shipping_address: Option<Encryption>,
    pub customer_present: Option<bool>,
    pub description: Option<common_utils::types::Description>,
    pub return_url: Option<common_utils::types::Url>,
    pub setup_future_usage: Option<storage_enums::FutureUsage>,
    pub apply_mit_exemption: Option<bool>,
    pub statement_descriptor: Option<common_utils::types::StatementDescriptor>,
    pub order_details: Option<Vec<masking::Secret<OrderDetailsWithAmount>>>,
    pub allowed_payment_method_types: Option<pii::SecretSerdeValue>,
    pub metadata: Option<pii::SecretSerdeValue>,
    pub connector_metadata: Option<pii::SecretSerdeValue>,
    pub feature_metadata: Option<FeatureMetadata>,
    pub payment_link_config: Option<PaymentLinkConfigRequestForPayments>,
    pub request_incremental_authorization: Option<RequestIncrementalAuthorization>,
    pub session_expiry: Option<PrimitiveDateTime>,
    pub frm_metadata: Option<pii::SecretSerdeValue>,
    pub request_external_three_ds_authentication: Option<bool>,
    pub updated_by: String,
    pub force_3ds_challenge: Option<bool>,
    pub is_iframe_redirection_enabled: Option<bool>,
    pub enable_partial_authorization: Option<EnablePartialAuthorizationBool>,
}

#[cfg(feature = "v2")]
impl PaymentIntentUpdateInternal {
    pub fn apply_changeset(self, source: PaymentIntent) -> PaymentIntent {
        let Self {
            status,
            prerouting_algorithm,
            amount_captured,
            modified_at: _, // This will be ignored from self
            active_attempt_id,
            active_attempts_group_id,
            active_attempt_id_type,
            amount,
            currency,
            shipping_cost,
            tax_details,
            skip_external_tax_calculation,
            surcharge_applicable,
            surcharge_amount,
            tax_on_surcharge,
            routing_algorithm_id,
            capture_method,
            authentication_type,
            billing_address,
            shipping_address,
            customer_present,
            description,
            return_url,
            setup_future_usage,
            apply_mit_exemption,
            statement_descriptor,
            order_details,
            allowed_payment_method_types,
            metadata,
            connector_metadata,
            feature_metadata,
            payment_link_config,
            request_incremental_authorization,
            session_expiry,
            frm_metadata,
            request_external_three_ds_authentication,
            updated_by,
            force_3ds_challenge,
            is_iframe_redirection_enabled,
            enable_partial_authorization,
        } = self;

        PaymentIntent {
            status: status.unwrap_or(source.status),
            prerouting_algorithm: prerouting_algorithm.or(source.prerouting_algorithm),
            amount_captured: amount_captured.or(source.amount_captured),
            modified_at: common_utils::date_time::now(),
            active_attempt_id: match active_attempt_id {
                Some(v_option) => v_option,
                None => source.active_attempt_id,
            },
            active_attempt_id_type: active_attempt_id_type.or(source.active_attempt_id_type),
            active_attempts_group_id: active_attempts_group_id.or(source.active_attempts_group_id),
            amount: amount.unwrap_or(source.amount),
            currency: currency.unwrap_or(source.currency),
            shipping_cost: shipping_cost.or(source.shipping_cost),
            tax_details: tax_details.or(source.tax_details),
            skip_external_tax_calculation: skip_external_tax_calculation
                .or(source.skip_external_tax_calculation),
            surcharge_applicable: surcharge_applicable.or(source.surcharge_applicable),
            surcharge_amount: surcharge_amount.or(source.surcharge_amount),
            tax_on_surcharge: tax_on_surcharge.or(source.tax_on_surcharge),
            routing_algorithm_id: routing_algorithm_id.or(source.routing_algorithm_id),
            capture_method: capture_method.or(source.capture_method),
            authentication_type: authentication_type.or(source.authentication_type),
            billing_address: billing_address.or(source.billing_address),
            shipping_address: shipping_address.or(source.shipping_address),
            customer_present: customer_present.or(source.customer_present),
            description: description.or(source.description),
            return_url: return_url.or(source.return_url),
            setup_future_usage: setup_future_usage.or(source.setup_future_usage),
            apply_mit_exemption: apply_mit_exemption.or(source.apply_mit_exemption),
            statement_descriptor: statement_descriptor.or(source.statement_descriptor),
            order_details: order_details.or(source.order_details),
            allowed_payment_method_types: allowed_payment_method_types
                .or(source.allowed_payment_method_types),
            metadata: metadata.or(source.metadata),
            connector_metadata: connector_metadata.or(source.connector_metadata),
            feature_metadata: feature_metadata.or(source.feature_metadata),
            payment_link_config: payment_link_config.or(source.payment_link_config),
            request_incremental_authorization: request_incremental_authorization
                .or(source.request_incremental_authorization),
            session_expiry: session_expiry.unwrap_or(source.session_expiry),
            frm_metadata: frm_metadata.or(source.frm_metadata),
            request_external_three_ds_authentication: request_external_three_ds_authentication
                .or(source.request_external_three_ds_authentication),
            updated_by,
            force_3ds_challenge: force_3ds_challenge.or(source.force_3ds_challenge),
            is_iframe_redirection_enabled: is_iframe_redirection_enabled
                .or(source.is_iframe_redirection_enabled),
            // Fields from source
            merchant_id: source.merchant_id,
            customer_id: source.customer_id,
            created_at: source.created_at,
            last_synced: source.last_synced,
            attempt_count: source.attempt_count,
            profile_id: source.profile_id,
            payment_link_id: source.payment_link_id,
            authorization_count: source.authorization_count,
            customer_details: source.customer_details,
            organization_id: source.organization_id,
            request_extended_authorization: source.request_extended_authorization,
            psd2_sca_exemption_type: source.psd2_sca_exemption_type,
            split_payments: source.split_payments,
            platform_merchant_id: source.platform_merchant_id,
            force_3ds_challenge_trigger: source.force_3ds_challenge_trigger,
            processor_merchant_id: source.processor_merchant_id,
            created_by: source.created_by,
            merchant_reference_id: source.merchant_reference_id,
            frm_merchant_decision: source.frm_merchant_decision,
            enable_payment_link: source.enable_payment_link,
            id: source.id,
            is_payment_id_from_merchant: source.is_payment_id_from_merchant,
            payment_channel: source.payment_channel,
            tax_status: source.tax_status,
            discount_amount: source.discount_amount,
            shipping_amount_tax: source.shipping_amount_tax,
            duty_amount: source.duty_amount,
            order_date: source.order_date,
            enable_partial_authorization: source.enable_partial_authorization,
            split_txns_enabled: source.split_txns_enabled,
            enable_overcapture: None,
            mit_category: None,
            billing_descriptor: source.billing_descriptor,
            tokenization: None,
            partner_merchant_identifier_details: source.partner_merchant_identifier_details,
        }
    }
}

#[cfg(feature = "v1")]
#[derive(Clone, Debug, AsChangeset, router_derive::DebugAsDisplay)]
#[diesel(table_name = payment_intent)]
pub struct PaymentIntentUpdateInternal {
    pub amount: Option<MinorUnit>,
    pub currency: Option<storage_enums::Currency>,
    pub status: Option<storage_enums::IntentStatus>,
    pub amount_captured: Option<MinorUnit>,
    pub customer_id: Option<common_utils::id_type::CustomerId>,
    pub return_url: Option<String>,
    pub setup_future_usage: Option<storage_enums::FutureUsage>,
    pub off_session: Option<bool>,
    pub metadata: Option<serde_json::Value>,
    pub billing_address_id: Option<String>,
    pub shipping_address_id: Option<String>,
    pub modified_at: PrimitiveDateTime,
    pub active_attempt_id: Option<String>,
    pub business_country: Option<storage_enums::CountryAlpha2>,
    pub business_label: Option<String>,
    pub description: Option<String>,
    pub statement_descriptor_name: Option<String>,
    pub statement_descriptor_suffix: Option<String>,
    #[diesel(deserialize_as = super::OptionalDieselArray<pii::SecretSerdeValue>)]
    pub order_details: Option<Vec<pii::SecretSerdeValue>>,
    pub attempt_count: Option<i16>,
    pub merchant_decision: Option<String>,
    pub payment_confirm_source: Option<storage_enums::PaymentSource>,
    pub updated_by: String,
    pub surcharge_applicable: Option<bool>,
    pub incremental_authorization_allowed: Option<bool>,
    pub authorization_count: Option<i32>,
    pub session_expiry: Option<PrimitiveDateTime>,
    pub fingerprint_id: Option<String>,
    pub request_external_three_ds_authentication: Option<bool>,
    pub frm_metadata: Option<pii::SecretSerdeValue>,
    pub customer_details: Option<Encryption>,
    pub billing_details: Option<Encryption>,
    pub merchant_order_reference_id: Option<String>,
    pub shipping_details: Option<Encryption>,
    pub is_payment_processor_token_flow: Option<bool>,
    pub tax_details: Option<TaxDetails>,
    pub force_3ds_challenge: Option<bool>,
    pub is_iframe_redirection_enabled: Option<bool>,
    pub extended_return_url: Option<String>,
    pub payment_channel: Option<common_enums::PaymentChannel>,
    pub feature_metadata: Option<masking::Secret<serde_json::Value>>,
    pub tax_status: Option<common_enums::TaxStatus>,
    pub discount_amount: Option<MinorUnit>,
    pub order_date: Option<PrimitiveDateTime>,
    pub shipping_amount_tax: Option<MinorUnit>,
    pub duty_amount: Option<MinorUnit>,
    pub enable_partial_authorization: Option<EnablePartialAuthorizationBool>,
    pub enable_overcapture: Option<common_types::primitive_wrappers::EnableOvercaptureBool>,
}

#[cfg(feature = "v1")]
impl PaymentIntentUpdate {
    pub fn apply_changeset(self, source: PaymentIntent) -> PaymentIntent {
        let PaymentIntentUpdateInternal {
            amount,
            currency,
            status,
            amount_captured,
            customer_id,
            return_url,
            setup_future_usage,
            off_session,
            metadata,
            billing_address_id,
            shipping_address_id,
            modified_at: _,
            active_attempt_id,
            business_country,
            business_label,
            description,
            statement_descriptor_name,
            statement_descriptor_suffix,
            order_details,
            attempt_count,
            merchant_decision,
            payment_confirm_source,
            updated_by,
            surcharge_applicable,
            incremental_authorization_allowed,
            authorization_count,
            session_expiry,
            fingerprint_id,
            request_external_three_ds_authentication,
            frm_metadata,
            customer_details,
            billing_details,
            merchant_order_reference_id,
            shipping_details,
            is_payment_processor_token_flow,
            tax_details,
            force_3ds_challenge,
            is_iframe_redirection_enabled,
            extended_return_url,
            payment_channel,
            feature_metadata,
            tax_status,
            discount_amount,
            order_date,
            shipping_amount_tax,
            duty_amount,
            enable_partial_authorization,
            enable_overcapture,
        } = self.into();
        PaymentIntent {
            amount: amount.unwrap_or(source.amount),
            currency: currency.or(source.currency),
            status: status.unwrap_or(source.status),
            amount_captured: amount_captured.or(source.amount_captured),
            customer_id: customer_id.or(source.customer_id),
            return_url: return_url.or(source.return_url),
            setup_future_usage: setup_future_usage.or(source.setup_future_usage),
            off_session: off_session.or(source.off_session),
            metadata: metadata.or(source.metadata),
            billing_address_id: billing_address_id.or(source.billing_address_id),
            shipping_address_id: shipping_address_id.or(source.shipping_address_id),
            modified_at: common_utils::date_time::now(),
            active_attempt_id: active_attempt_id.unwrap_or(source.active_attempt_id),
            business_country: business_country.or(source.business_country),
            business_label: business_label.or(source.business_label),
            description: description.or(source.description),
            statement_descriptor_name: statement_descriptor_name
                .or(source.statement_descriptor_name),
            statement_descriptor_suffix: statement_descriptor_suffix
                .or(source.statement_descriptor_suffix),
            order_details: order_details.or(source.order_details),
            attempt_count: attempt_count.unwrap_or(source.attempt_count),
            merchant_decision: merchant_decision.or(source.merchant_decision),
            payment_confirm_source: payment_confirm_source.or(source.payment_confirm_source),
            updated_by,
            surcharge_applicable: surcharge_applicable.or(source.surcharge_applicable),

            incremental_authorization_allowed: incremental_authorization_allowed
                .or(source.incremental_authorization_allowed),
            authorization_count: authorization_count.or(source.authorization_count),
            fingerprint_id: fingerprint_id.or(source.fingerprint_id),
            session_expiry: session_expiry.or(source.session_expiry),
            request_external_three_ds_authentication: request_external_three_ds_authentication
                .or(source.request_external_three_ds_authentication),
            frm_metadata: frm_metadata.or(source.frm_metadata),
            customer_details: customer_details.or(source.customer_details),
            billing_details: billing_details.or(source.billing_details),
            merchant_order_reference_id: merchant_order_reference_id
                .or(source.merchant_order_reference_id),
            shipping_details: shipping_details.or(source.shipping_details),
            is_payment_processor_token_flow: is_payment_processor_token_flow
                .or(source.is_payment_processor_token_flow),
            tax_details: tax_details.or(source.tax_details),
            force_3ds_challenge: force_3ds_challenge.or(source.force_3ds_challenge),
            is_iframe_redirection_enabled: is_iframe_redirection_enabled
                .or(source.is_iframe_redirection_enabled),
            extended_return_url: extended_return_url.or(source.extended_return_url),
            payment_channel: payment_channel.or(source.payment_channel),
            feature_metadata: feature_metadata
                .map(|value| value.expose())
                .or(source.feature_metadata),
            tax_status: tax_status.or(source.tax_status),
            discount_amount: discount_amount.or(source.discount_amount),
            order_date: order_date.or(source.order_date),
            shipping_amount_tax: shipping_amount_tax.or(source.shipping_amount_tax),
            duty_amount: duty_amount.or(source.duty_amount),
            enable_partial_authorization: enable_partial_authorization
                .or(source.enable_partial_authorization),
            enable_overcapture: enable_overcapture.or(source.enable_overcapture),
            ..source
        }
    }
}

#[cfg(feature = "v1")]
impl From<PaymentIntentUpdate> for PaymentIntentUpdateInternal {
    fn from(payment_intent_update: PaymentIntentUpdate) -> Self {
        match payment_intent_update {
            PaymentIntentUpdate::MetadataUpdate {
                metadata,
                updated_by,
            } => Self {
                metadata: Some(metadata),
                modified_at: common_utils::date_time::now(),
                updated_by,
                amount: None,
                currency: None,
                status: None,
                amount_captured: None,
                customer_id: None,
                return_url: None,
                setup_future_usage: None,
                off_session: None,
                billing_address_id: None,
                shipping_address_id: None,
                active_attempt_id: None,
                business_country: None,
                business_label: None,
                description: None,
                statement_descriptor_name: None,
                statement_descriptor_suffix: None,
                order_details: None,
                attempt_count: None,
                merchant_decision: None,
                payment_confirm_source: None,
                surcharge_applicable: None,
                incremental_authorization_allowed: None,
                authorization_count: None,
                session_expiry: None,
                fingerprint_id: None,
                request_external_three_ds_authentication: None,
                frm_metadata: None,
                customer_details: None,
                billing_details: None,
                merchant_order_reference_id: None,
                shipping_details: None,
                is_payment_processor_token_flow: None,
                tax_details: None,
                force_3ds_challenge: None,
                is_iframe_redirection_enabled: None,
                extended_return_url: None,
                payment_channel: None,
                feature_metadata: None,
                tax_status: None,
                discount_amount: None,
                order_date: None,
                shipping_amount_tax: None,
                duty_amount: None,
                enable_partial_authorization: None,
                enable_overcapture: None,
            },
            PaymentIntentUpdate::Update(value) => Self {
                amount: Some(value.amount),
                currency: Some(value.currency),
                setup_future_usage: value.setup_future_usage,
                status: Some(value.status),
                customer_id: value.customer_id,
                shipping_address_id: value.shipping_address_id,
                billing_address_id: value.billing_address_id,
                return_url: None, // deprecated
                business_country: value.business_country,
                business_label: value.business_label,
                description: value.description,
                statement_descriptor_name: value.statement_descriptor_name,
                statement_descriptor_suffix: value.statement_descriptor_suffix,
                order_details: value.order_details,
                metadata: value.metadata,
                payment_confirm_source: value.payment_confirm_source,
                updated_by: value.updated_by,
                session_expiry: value.session_expiry,
                fingerprint_id: value.fingerprint_id,
                request_external_three_ds_authentication: value
                    .request_external_three_ds_authentication,
                frm_metadata: value.frm_metadata,
                customer_details: value.customer_details,
                billing_details: value.billing_details,
                merchant_order_reference_id: value.merchant_order_reference_id,
                shipping_details: value.shipping_details,
                amount_captured: None,
                off_session: None,
                modified_at: common_utils::date_time::now(),
                active_attempt_id: None,
                attempt_count: None,
                merchant_decision: None,
                surcharge_applicable: None,
                incremental_authorization_allowed: None,
                authorization_count: None,
                is_payment_processor_token_flow: value.is_payment_processor_token_flow,
                tax_details: None,
                force_3ds_challenge: value.force_3ds_challenge,
                is_iframe_redirection_enabled: value.is_iframe_redirection_enabled,
                extended_return_url: value.return_url,
                payment_channel: value.payment_channel,
                feature_metadata: value.feature_metadata,
                tax_status: value.tax_status,
                discount_amount: value.discount_amount,
                order_date: value.order_date,
                shipping_amount_tax: value.shipping_amount_tax,
                duty_amount: value.duty_amount,
                enable_partial_authorization: value.enable_partial_authorization,
                enable_overcapture: value.enable_overcapture,
            },
            PaymentIntentUpdate::PaymentCreateUpdate {
                return_url,
                status,
                customer_id,
                shipping_address_id,
                billing_address_id,
                customer_details,
                updated_by,
            } => Self {
                return_url: None, // deprecated
                status,
                customer_id,
                shipping_address_id,
                billing_address_id,
                customer_details,
                modified_at: common_utils::date_time::now(),
                updated_by,
                amount: None,
                currency: None,
                amount_captured: None,
                setup_future_usage: None,
                off_session: None,
                metadata: None,
                active_attempt_id: None,
                business_country: None,
                business_label: None,
                description: None,
                statement_descriptor_name: None,
                statement_descriptor_suffix: None,
                order_details: None,
                attempt_count: None,
                merchant_decision: None,
                payment_confirm_source: None,
                surcharge_applicable: None,
                incremental_authorization_allowed: None,
                authorization_count: None,
                session_expiry: None,
                fingerprint_id: None,
                request_external_three_ds_authentication: None,
                frm_metadata: None,
                billing_details: None,
                merchant_order_reference_id: None,
                shipping_details: None,
                is_payment_processor_token_flow: None,
                tax_details: None,
                force_3ds_challenge: None,
                is_iframe_redirection_enabled: None,
                extended_return_url: return_url,
                payment_channel: None,
                feature_metadata: None,
                tax_status: None,
                discount_amount: None,
                order_date: None,
                shipping_amount_tax: None,
                duty_amount: None,
                enable_partial_authorization: None,
                enable_overcapture: None,
            },
            PaymentIntentUpdate::PGStatusUpdate {
                status,
                updated_by,
                incremental_authorization_allowed,
                feature_metadata,
            } => Self {
                status: Some(status),
                modified_at: common_utils::date_time::now(),
                updated_by,
                incremental_authorization_allowed,
                amount: None,
                currency: None,
                amount_captured: None,
                customer_id: None,
                return_url: None,
                setup_future_usage: None,
                off_session: None,
                metadata: None,
                billing_address_id: None,
                shipping_address_id: None,
                active_attempt_id: None,
                business_country: None,
                business_label: None,
                description: None,
                statement_descriptor_name: None,
                statement_descriptor_suffix: None,
                order_details: None,
                attempt_count: None,
                merchant_decision: None,
                payment_confirm_source: None,
                surcharge_applicable: None,
                authorization_count: None,
                session_expiry: None,
                fingerprint_id: None,
                request_external_three_ds_authentication: None,
                frm_metadata: None,
                customer_details: None,
                billing_details: None,
                merchant_order_reference_id: None,
                shipping_details: None,
                is_payment_processor_token_flow: None,
                tax_details: None,
                force_3ds_challenge: None,
                is_iframe_redirection_enabled: None,
                extended_return_url: None,
                payment_channel: None,
                feature_metadata,
                tax_status: None,
                discount_amount: None,
                order_date: None,
                shipping_amount_tax: None,
                duty_amount: None,
                enable_partial_authorization: None,
                enable_overcapture: None,
            },
            PaymentIntentUpdate::MerchantStatusUpdate {
                status,
                shipping_address_id,
                billing_address_id,
                updated_by,
            } => Self {
                status: Some(status),
                shipping_address_id,
                billing_address_id,
                modified_at: common_utils::date_time::now(),
                updated_by,
                amount: None,
                currency: None,
                amount_captured: None,
                customer_id: None,
                return_url: None,
                setup_future_usage: None,
                off_session: None,
                metadata: None,
                active_attempt_id: None,
                business_country: None,
                business_label: None,
                description: None,
                statement_descriptor_name: None,
                statement_descriptor_suffix: None,
                order_details: None,
                attempt_count: None,
                merchant_decision: None,
                payment_confirm_source: None,
                surcharge_applicable: None,
                incremental_authorization_allowed: None,
                authorization_count: None,
                session_expiry: None,
                fingerprint_id: None,
                request_external_three_ds_authentication: None,
                frm_metadata: None,
                customer_details: None,
                billing_details: None,
                merchant_order_reference_id: None,
                shipping_details: None,
                is_payment_processor_token_flow: None,
                tax_details: None,
                force_3ds_challenge: None,
                is_iframe_redirection_enabled: None,
                extended_return_url: None,
                payment_channel: None,
                feature_metadata: None,
                tax_status: None,
                discount_amount: None,
                order_date: None,
                shipping_amount_tax: None,
                duty_amount: None,
                enable_partial_authorization: None,
                enable_overcapture: None,
            },
            PaymentIntentUpdate::ResponseUpdate {
                // amount,
                // currency,
                status,
                amount_captured,
                fingerprint_id,
                // customer_id,
                updated_by,
                incremental_authorization_allowed,
                feature_metadata,
            } => Self {
                // amount,
                // currency: Some(currency),
                status: Some(status),
                amount_captured,
                fingerprint_id,
                // customer_id,
                return_url: None,
                modified_at: common_utils::date_time::now(),
                updated_by,
                incremental_authorization_allowed,
                amount: None,
                currency: None,
                customer_id: None,
                setup_future_usage: None,
                off_session: None,
                metadata: None,
                billing_address_id: None,
                shipping_address_id: None,
                active_attempt_id: None,
                business_country: None,
                business_label: None,
                description: None,
                statement_descriptor_name: None,
                statement_descriptor_suffix: None,
                order_details: None,
                attempt_count: None,
                merchant_decision: None,
                payment_confirm_source: None,
                surcharge_applicable: None,
                authorization_count: None,
                session_expiry: None,
                request_external_three_ds_authentication: None,
                frm_metadata: None,
                customer_details: None,
                billing_details: None,
                merchant_order_reference_id: None,
                shipping_details: None,
                is_payment_processor_token_flow: None,
                tax_details: None,
                force_3ds_challenge: None,
                is_iframe_redirection_enabled: None,
                extended_return_url: None,
                payment_channel: None,
                feature_metadata,
                tax_status: None,
                discount_amount: None,
                order_date: None,
                shipping_amount_tax: None,
                duty_amount: None,
                enable_partial_authorization: None,
                enable_overcapture: None,
            },
            PaymentIntentUpdate::PaymentAttemptAndAttemptCountUpdate {
                active_attempt_id,
                attempt_count,
                updated_by,
            } => Self {
                active_attempt_id: Some(active_attempt_id),
                attempt_count: Some(attempt_count),
                updated_by,
                amount: None,
                currency: None,
                status: None,
                amount_captured: None,
                customer_id: None,
                return_url: None,
                setup_future_usage: None,
                off_session: None,
                metadata: None,
                billing_address_id: None,
                shipping_address_id: None,
                modified_at: common_utils::date_time::now(),
                business_country: None,
                business_label: None,
                description: None,
                statement_descriptor_name: None,
                statement_descriptor_suffix: None,
                order_details: None,
                merchant_decision: None,
                payment_confirm_source: None,
                surcharge_applicable: None,
                incremental_authorization_allowed: None,
                authorization_count: None,
                session_expiry: None,
                fingerprint_id: None,
                request_external_three_ds_authentication: None,
                frm_metadata: None,
                customer_details: None,
                billing_details: None,
                merchant_order_reference_id: None,
                shipping_details: None,
                is_payment_processor_token_flow: None,
                tax_details: None,
                force_3ds_challenge: None,
                is_iframe_redirection_enabled: None,
                extended_return_url: None,
                payment_channel: None,
                feature_metadata: None,
                tax_status: None,
                discount_amount: None,
                order_date: None,
                shipping_amount_tax: None,
                duty_amount: None,
                enable_partial_authorization: None,
                enable_overcapture: None,
            },
            PaymentIntentUpdate::StatusAndAttemptUpdate {
                status,
                active_attempt_id,
                attempt_count,
                updated_by,
            } => Self {
                status: Some(status),
                active_attempt_id: Some(active_attempt_id),
                attempt_count: Some(attempt_count),
                updated_by,
                amount: None,
                currency: None,
                amount_captured: None,
                customer_id: None,
                return_url: None,
                setup_future_usage: None,
                off_session: None,
                metadata: None,
                billing_address_id: None,
                shipping_address_id: None,
                modified_at: common_utils::date_time::now(),
                business_country: None,
                business_label: None,
                description: None,
                statement_descriptor_name: None,
                statement_descriptor_suffix: None,
                order_details: None,
                merchant_decision: None,
                payment_confirm_source: None,
                surcharge_applicable: None,
                incremental_authorization_allowed: None,
                authorization_count: None,
                session_expiry: None,
                fingerprint_id: None,
                request_external_three_ds_authentication: None,
                frm_metadata: None,
                customer_details: None,
                billing_details: None,
                merchant_order_reference_id: None,
                shipping_details: None,
                is_payment_processor_token_flow: None,
                tax_details: None,
                force_3ds_challenge: None,
                is_iframe_redirection_enabled: None,
                extended_return_url: None,
                payment_channel: None,
                feature_metadata: None,
                tax_status: None,
                discount_amount: None,
                order_date: None,
                shipping_amount_tax: None,
                duty_amount: None,
                enable_partial_authorization: None,
                enable_overcapture: None,
            },
            PaymentIntentUpdate::ApproveUpdate {
                status,
                merchant_decision,
                updated_by,
            } => Self {
                status: Some(status),
                merchant_decision,
                updated_by,
                amount: None,
                currency: None,
                amount_captured: None,
                customer_id: None,
                return_url: None,
                setup_future_usage: None,
                off_session: None,
                metadata: None,
                billing_address_id: None,
                shipping_address_id: None,
                modified_at: common_utils::date_time::now(),
                active_attempt_id: None,
                business_country: None,
                business_label: None,
                description: None,
                statement_descriptor_name: None,
                statement_descriptor_suffix: None,
                order_details: None,
                attempt_count: None,
                payment_confirm_source: None,
                surcharge_applicable: None,
                incremental_authorization_allowed: None,
                authorization_count: None,
                session_expiry: None,
                fingerprint_id: None,
                request_external_three_ds_authentication: None,
                frm_metadata: None,
                customer_details: None,
                billing_details: None,
                merchant_order_reference_id: None,
                shipping_details: None,
                is_payment_processor_token_flow: None,
                tax_details: None,
                force_3ds_challenge: None,
                is_iframe_redirection_enabled: None,
                extended_return_url: None,
                payment_channel: None,
                feature_metadata: None,
                tax_status: None,
                discount_amount: None,
                order_date: None,
                shipping_amount_tax: None,
                duty_amount: None,
                enable_partial_authorization: None,
                enable_overcapture: None,
            },
            PaymentIntentUpdate::RejectUpdate {
                status,
                merchant_decision,
                updated_by,
            } => Self {
                status: Some(status),
                merchant_decision,
                updated_by,
                amount: None,
                currency: None,
                amount_captured: None,
                customer_id: None,
                return_url: None,
                setup_future_usage: None,
                off_session: None,
                metadata: None,
                billing_address_id: None,
                shipping_address_id: None,
                modified_at: common_utils::date_time::now(),
                active_attempt_id: None,
                business_country: None,
                business_label: None,
                description: None,
                statement_descriptor_name: None,
                statement_descriptor_suffix: None,
                order_details: None,
                attempt_count: None,
                payment_confirm_source: None,
                surcharge_applicable: None,
                incremental_authorization_allowed: None,
                authorization_count: None,
                session_expiry: None,
                fingerprint_id: None,
                request_external_three_ds_authentication: None,
                frm_metadata: None,
                customer_details: None,
                billing_details: None,
                merchant_order_reference_id: None,
                shipping_details: None,
                is_payment_processor_token_flow: None,
                tax_details: None,
                force_3ds_challenge: None,
                is_iframe_redirection_enabled: None,
                extended_return_url: None,
                payment_channel: None,
                feature_metadata: None,
                tax_status: None,
                discount_amount: None,
                order_date: None,
                shipping_amount_tax: None,
                duty_amount: None,
                enable_partial_authorization: None,
                enable_overcapture: None,
            },
            PaymentIntentUpdate::SurchargeApplicableUpdate {
                surcharge_applicable,
                updated_by,
            } => Self {
                surcharge_applicable,
                updated_by,
                amount: None,
                currency: None,
                status: None,
                amount_captured: None,
                customer_id: None,
                return_url: None,
                setup_future_usage: None,
                off_session: None,
                metadata: None,
                billing_address_id: None,
                shipping_address_id: None,
                modified_at: common_utils::date_time::now(),
                active_attempt_id: None,
                business_country: None,
                business_label: None,
                description: None,
                statement_descriptor_name: None,
                statement_descriptor_suffix: None,
                order_details: None,
                attempt_count: None,
                merchant_decision: None,
                payment_confirm_source: None,
                incremental_authorization_allowed: None,
                authorization_count: None,
                session_expiry: None,
                fingerprint_id: None,
                request_external_three_ds_authentication: None,
                frm_metadata: None,
                customer_details: None,
                billing_details: None,
                merchant_order_reference_id: None,
                shipping_details: None,
                is_payment_processor_token_flow: None,
                tax_details: None,
                force_3ds_challenge: None,
                is_iframe_redirection_enabled: None,
                extended_return_url: None,
                payment_channel: None,
                feature_metadata: None,
                tax_status: None,
                discount_amount: None,
                order_date: None,
                shipping_amount_tax: None,
                duty_amount: None,
                enable_partial_authorization: None,
                enable_overcapture: None,
            },
            PaymentIntentUpdate::IncrementalAuthorizationAmountUpdate { amount } => Self {
                amount: Some(amount),
                currency: None,
                status: None,
                amount_captured: None,
                customer_id: None,
                return_url: None,
                setup_future_usage: None,
                off_session: None,
                metadata: None,
                billing_address_id: None,
                shipping_address_id: None,
                modified_at: common_utils::date_time::now(),
                active_attempt_id: None,
                business_country: None,
                business_label: None,
                description: None,
                statement_descriptor_name: None,
                statement_descriptor_suffix: None,
                order_details: None,
                attempt_count: None,
                merchant_decision: None,
                payment_confirm_source: None,
                updated_by: String::default(),
                surcharge_applicable: None,
                incremental_authorization_allowed: None,
                authorization_count: None,
                session_expiry: None,
                fingerprint_id: None,
                request_external_three_ds_authentication: None,
                frm_metadata: None,
                customer_details: None,
                billing_details: None,
                merchant_order_reference_id: None,
                shipping_details: None,
                is_payment_processor_token_flow: None,
                tax_details: None,
                force_3ds_challenge: None,
                is_iframe_redirection_enabled: None,
                extended_return_url: None,
                payment_channel: None,
                feature_metadata: None,
                tax_status: None,
                discount_amount: None,
                order_date: None,
                shipping_amount_tax: None,
                duty_amount: None,
                enable_partial_authorization: None,
                enable_overcapture: None,
            },
            PaymentIntentUpdate::AuthorizationCountUpdate {
                authorization_count,
            } => Self {
                authorization_count: Some(authorization_count),
                amount: None,
                currency: None,
                status: None,
                amount_captured: None,
                customer_id: None,
                return_url: None,
                setup_future_usage: None,
                off_session: None,
                metadata: None,
                billing_address_id: None,
                shipping_address_id: None,
                modified_at: common_utils::date_time::now(),
                active_attempt_id: None,
                business_country: None,
                business_label: None,
                description: None,
                statement_descriptor_name: None,
                statement_descriptor_suffix: None,
                order_details: None,
                attempt_count: None,
                merchant_decision: None,
                payment_confirm_source: None,
                updated_by: String::default(),
                surcharge_applicable: None,
                incremental_authorization_allowed: None,
                session_expiry: None,
                fingerprint_id: None,
                request_external_three_ds_authentication: None,
                frm_metadata: None,
                customer_details: None,
                billing_details: None,
                merchant_order_reference_id: None,
                shipping_details: None,
                is_payment_processor_token_flow: None,
                tax_details: None,
                force_3ds_challenge: None,
                is_iframe_redirection_enabled: None,
                extended_return_url: None,
                payment_channel: None,
                feature_metadata: None,
                tax_status: None,
                discount_amount: None,
                order_date: None,
                shipping_amount_tax: None,
                duty_amount: None,
                enable_partial_authorization: None,
                enable_overcapture: None,
            },
            PaymentIntentUpdate::CompleteAuthorizeUpdate {
                shipping_address_id,
            } => Self {
                shipping_address_id,
                amount: None,
                currency: None,
                status: None,
                amount_captured: None,
                customer_id: None,
                return_url: None,
                setup_future_usage: None,
                off_session: None,
                metadata: None,
                billing_address_id: None,
                modified_at: common_utils::date_time::now(),
                active_attempt_id: None,
                business_country: None,
                business_label: None,
                description: None,
                statement_descriptor_name: None,
                statement_descriptor_suffix: None,
                order_details: None,
                attempt_count: None,
                merchant_decision: None,
                payment_confirm_source: None,
                updated_by: String::default(),
                surcharge_applicable: None,
                incremental_authorization_allowed: None,
                authorization_count: None,
                session_expiry: None,
                fingerprint_id: None,
                request_external_three_ds_authentication: None,
                frm_metadata: None,
                customer_details: None,
                billing_details: None,
                merchant_order_reference_id: None,
                shipping_details: None,
                is_payment_processor_token_flow: None,
                tax_details: None,
                force_3ds_challenge: None,
                is_iframe_redirection_enabled: None,
                extended_return_url: None,
                payment_channel: None,
                feature_metadata: None,
                tax_status: None,
                discount_amount: None,
                order_date: None,
                shipping_amount_tax: None,
                duty_amount: None,
                enable_partial_authorization: None,
                enable_overcapture: None,
            },
            PaymentIntentUpdate::ManualUpdate { status, updated_by } => Self {
                status,
                updated_by,
                amount: None,
                currency: None,
                amount_captured: None,
                customer_id: None,
                return_url: None,
                setup_future_usage: None,
                off_session: None,
                metadata: None,
                billing_address_id: None,
                shipping_address_id: None,
                modified_at: common_utils::date_time::now(),
                active_attempt_id: None,
                business_country: None,
                business_label: None,
                description: None,
                statement_descriptor_name: None,
                statement_descriptor_suffix: None,
                order_details: None,
                attempt_count: None,
                merchant_decision: None,
                payment_confirm_source: None,
                surcharge_applicable: None,
                incremental_authorization_allowed: None,
                authorization_count: None,
                session_expiry: None,
                fingerprint_id: None,
                request_external_three_ds_authentication: None,
                frm_metadata: None,
                customer_details: None,
                billing_details: None,
                merchant_order_reference_id: None,
                shipping_details: None,
                is_payment_processor_token_flow: None,
                tax_details: None,
                force_3ds_challenge: None,
                is_iframe_redirection_enabled: None,
                extended_return_url: None,
                payment_channel: None,
                feature_metadata: None,
                tax_status: None,
                discount_amount: None,
                order_date: None,
                shipping_amount_tax: None,
                duty_amount: None,
                enable_partial_authorization: None,
                enable_overcapture: None,
            },
            PaymentIntentUpdate::SessionResponseUpdate {
                tax_details,
                shipping_address_id,
                updated_by,
                shipping_details,
            } => Self {
                shipping_address_id,
                amount: None,
                tax_details: Some(tax_details),
                currency: None,
                status: None,
                amount_captured: None,
                customer_id: None,
                return_url: None,
                setup_future_usage: None,
                off_session: None,
                metadata: None,
                billing_address_id: None,
                modified_at: common_utils::date_time::now(),
                active_attempt_id: None,
                business_country: None,
                business_label: None,
                description: None,
                statement_descriptor_name: None,
                statement_descriptor_suffix: None,
                order_details: None,
                attempt_count: None,
                merchant_decision: None,
                payment_confirm_source: None,
                updated_by,
                surcharge_applicable: None,
                incremental_authorization_allowed: None,
                authorization_count: None,
                session_expiry: None,
                fingerprint_id: None,
                request_external_three_ds_authentication: None,
                frm_metadata: None,
                customer_details: None,
                billing_details: None,
                merchant_order_reference_id: None,
                shipping_details,
                is_payment_processor_token_flow: None,
                force_3ds_challenge: None,
                is_iframe_redirection_enabled: None,
                extended_return_url: None,
                payment_channel: None,
                feature_metadata: None,
                tax_status: None,
                discount_amount: None,
                order_date: None,
                shipping_amount_tax: None,
                duty_amount: None,
                enable_partial_authorization: None,
                enable_overcapture: None,
            },
        }
    }
}

mod tests {
    #[test]
    fn test_backwards_compatibility() {
        let serialized_payment_intent = r#"{
    "payment_id": "payment_12345",
    "merchant_id": "merchant_67890",
    "status": "succeeded",
    "amount": 10000,
    "currency": "USD",
    "amount_captured": null,
    "customer_id": "cust_123456",
    "description": "Test Payment",
    "return_url": "https://example.com/return",
    "metadata": null,
    "connector_id": "connector_001",
    "shipping_address_id": null,
    "billing_address_id": null,
    "statement_descriptor_name": null,
    "statement_descriptor_suffix": null,
    "created_at": "2024-02-01T12:00:00Z",
    "modified_at": "2024-02-01T12:00:00Z",
    "last_synced": null,
    "setup_future_usage": null,
    "off_session": null,
    "client_secret": "sec_abcdef1234567890",
    "active_attempt_id": "attempt_123",
    "business_country": "US",
    "business_label": null,
    "order_details": null,
    "allowed_payment_method_types": "credit",
    "connector_metadata": null,
    "feature_metadata": null,
    "attempt_count": 1,
    "profile_id": null,
    "merchant_decision": null,
    "payment_link_id": null,
    "payment_confirm_source": null,
    "updated_by": "admin",
    "surcharge_applicable": null,
    "request_incremental_authorization": null,
    "incremental_authorization_allowed": null,
    "authorization_count": null,
    "session_expiry": null,
    "fingerprint_id": null,
    "frm_metadata": null
}"#;
        let deserialized_payment_intent =
            serde_json::from_str::<super::PaymentIntent>(serialized_payment_intent);

        assert!(deserialized_payment_intent.is_ok());
    }
}
